﻿// 如果不能用，请下载chrome，没有白点表示不支持。缓存，流量，横向，最好有重力感应。
// 测试pad


// 所有长度单位数据单位是厘米
// 左边是x，前方是y, 上方是z

// 画虚线 ctx.dashedLine = function (x, y, x2, y2, dashArray)
// x, y, x2, y2 起止坐标，dashArray线段长度数组，格式：[实，空，实，空。。。]
/*var CP = window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype;
if (CP && CP.lineTo) {
CP.dashedLine = function (x, y, x2, y2, dashArray) {
if (!dashArray) dashArray = [10, 10];
if (dashLength == 0) dashLength = 0.001; // Hack for Safari
var dashCount = dashArray.length;
this.moveTo(x, y);
var dx = (x2 - x),
dy = (y2 - y);
var slope = dy / dx;
var distRemaining = Math.sqrt(dx * dx + dy * dy);
var dashIndex = 0,
draw = true;
while (distRemaining >= 0.1) {
var dashLength = dashArray[dashIndex++ % dashCount];
if (dashLength > distRemaining) dashLength = distRemaining;
var xStep = Math.sqrt(dashLength * dashLength / (1 + slope * slope));
if (dx < 0) xStep = -xStep;
x += xStep;
y += slope * xStep;
this[draw ? 'lineTo' : 'moveTo'](x, y);
distRemaining -= dashLength;
draw = !draw;
}
}
}
*/

// 全局变量
var degree01 = 0.001745329251994329576923690768489; // 0.1度对应的弧度
var degree1 = 0.01745329251994329576923690768489; // 1度对应的弧度
var degree90 = 1.5707963267948966192313216916398; // 90度对应的弧度

// 画垂直直线，x1 y1 y2 两个端点。
var lineHalfWidth = 1; // 默认的直线半宽度
var lineMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff, opacity: 0.8 }); // 默认的直线颜色

// 返回 THREE.Mesh
var hVerticalLine = function (x1, y1, y2) {
	var geometry = new THREE.Geometry(); //一个几何可以包含多个线条
	geometry.vertices.push(new THREE.Vector3(x1 - lineHalfWidth, y1, 0));
	geometry.vertices.push(new THREE.Vector3(x1, y1 + lineHalfWidth, 0));
	geometry.vertices.push(new THREE.Vector3(x1 + lineHalfWidth, y1, 0));
	geometry.vertices.push(new THREE.Vector3(x1 + lineHalfWidth, y2, 0));
	geometry.vertices.push(new THREE.Vector3(x1, y2 - lineHalfWidth, 0));
	geometry.vertices.push(new THREE.Vector3(x1 - lineHalfWidth, y2, 0));
	geometry.vertices.push(new THREE.Vector3(x1 - lineHalfWidth, y1, 0));
	var plane = new THREE.hShape(geometry, lineMaterial);
	return plane;
}

// 画水平直线，x1 x2 y1 两个端点。
// 返回 THREE.Mesh
var hHorizontalLine = function (x1, x2, y1) {
	var geometry = new THREE.Geometry(); //一个几何可以包含多个线条
	geometry.vertices.push(new THREE.Vector3(x1, y1 - lineHalfWidth, 0));
	geometry.vertices.push(new THREE.Vector3(x1, y1 + lineHalfWidth, 0));
	geometry.vertices.push(new THREE.Vector3(x2, y1 + lineHalfWidth, 0));
	geometry.vertices.push(new THREE.Vector3(x2, y1 - lineHalfWidth, 0));
	geometry.vertices.push(new THREE.Vector3(x1, y1 - lineHalfWidth, 0));
	//var material = new THREE.MeshBasicMaterial({ color: 0xffffff, opacity: 0.5 });
	var plane = new THREE.hShape(geometry, lineMaterial);
	return plane;
}

// 3d视口，id jq筛选器字符串，ca视角, ax ay az 绕轴的旋转角度,单位度，
// ax旋转90度是前方, ay区间是-2pi到+2pi之间, 0到-2pi是镜像视图
// px py pz 相机点, 前方是y, 上方是z，左边是x
function view3d(sce, id, ac, ax, ay, az, px, py, pz) {
	var scene = sce;
	var obj = document.getElementById(id);
	var viewW = obj.clientWidth;
	var viewH = obj.clientHeight;

	// 选择render方式，优先用WEBGL
	//	var renderer;
	//	try {
	//		renderer = new THREE.WebGLRenderer();
	//	}
	//	catch (err) {
	//		renderer = new THREE.CanvasRenderer();
	//	}
	var renderer = new THREE.CanvasRenderer();
	renderer.setSize(viewW, viewH);
	obj.appendChild(renderer.domElement);

	// 摄像机
	var camera = new THREE.PerspectiveCamera(ac, viewW / viewH, 0.1, 50000);
	// 相机相对于车坐标系的位置和角度
	camera.ax0 = ax;
	camera.ay0 = ay;
	camera.az0 = az;
	camera.x0 = px;
	camera.y0 = py;
	camera.z0 = pz;
	//camera.lookAt({ x: 1, y: 1, z: 0 });

	camera.rotation.x = ax;
	//camera.rotation.y = ax;
	camera.position.z = pz;

	if (ay < 0)	// 后视图镜向
		camera.scale = new THREE.Vector3(-1, 1, 1); 

	this.render = function () {
		//http://zhidao.baidu.com/link?url=kA-1AaUFxm7NQePFOh0Gr7bzL4vGvVPZcXV6uIQFzxbutz9uTitrhdeCc4mco6uZUVpwL99j0Th4YlPXYb76n_
		//向量（x， y）绕原点逆时针旋转角度A：[x,y] x [cosA sinA] = [x*cosA-y*sinA x*sinA+y*cosA]        

		// 以车的后轴中点为圆心旋转，相机旋转后还要移动相机位置
		var ang = -car.anglez - degree90 + camera.ay0; // 俯视图和其它视图差90度	
		var c = Math.cos(ang), s = Math.sin(ang);
		var xx = camera.x0 * c - camera.y0 * s; //[x,y] x [cosA sinA] = [x*cosA-y*sinA x*sinA+y*cosA] 
		var yy = camera.x0 * s + camera.y0 * c;
		// 加上车坐标
		//xx += car.x;
		//yy += car.y;

		camera.rotation.y = ang;
		camera.position.x = car.x - yy + Math.random();		// 加一点随机抖动
		camera.position.y = -car.y + xx + Math.random();

		renderer.render(scene, camera);

		// 背景图
		if (camera.ay0 < 0)	// 后视图镜向
			ang = -ang;
		obj.style.backgroundPosition = ang * 700 + "px " + (viewH / 2 - 180 + Math.random()) + "px";   // 求图片的位置，175是背景图的地平线的位置
	};


	//设置光源
	//			var light;
	//			function initLight() {
	//				light = new THREE.DirectionalLight(0xff0000, 1.0, 0); //设置平行光源
	//				light.position.set(200, 200, 200); //设置光源向量
	//				scene.add(light); // 追加光源到场景
	//			}

	//initLight();
	//render();
	//setInterval( render, 50 )	// 20帧
}

// 场景和汽车
var yellowStyle = "#ffcc00"; // 黄线颜色
var yellowLineMaterial = new THREE.MeshBasicMaterial({ color: 0xffcc00, opacity: 1 }); // 默认的直线颜色
var whiteStyle = "#dddddd"; // 白线颜色
var whiteLineMaterial = new THREE.MeshBasicMaterial({ color: 0xdddddd, opacity: 1 }); // 默认的直线颜色
var dashedStyle = "#888888"; // 虚线颜色，提高效率，简化程序，用接近色实线代替虚线
var dashedLineMaterial = new THREE.MeshBasicMaterial({ color: 0x888888, opacity: 1 }); // 默认的直线颜色


var frontScene = new THREE.Scene();  	// 前视图场景，包括两个侧视图
var frontGroup = new THREE.Object3D(); 	// 主场景元素。
var mirrorScene = new THREE.Scene(); 	// 反光镜场景，
var mirrorGroup = new THREE.Object3D(); // 反光镜场景元素。

var topScene;	// 二维俯视图，用canvas对象
var car; 	// 车，在俯视图中显示，用canvas对象
var speed1 = 6;	// 一档速度
var radianframe = degree1 * 1.52;	// 转弯时车轮每帧旋转弧度, 1.52度，25帧打满
var radianmax = degree1 * 38;	// 车轮最大弧度，相当于38弧度
var period = 100;	// 帧周期，毫秒

var render;	// 渲染
var operation;	// 重力操作区
var autopilot;	// 自动驾驶

// 页面载入时执行，发布编译时注释这一句
window.onload = function () {
    if (document.getElementById('operation') === null)  // 没有操作区直接返回
        return;

    // 重力操作区
    operation = new Operation(); // 只能在这里初始化，因为Operation要取DOM元素
    autopilot = new Autopilot();	// 自动驾驶

    // 建立场景
    // 俯视图场景
    topScene = new TopScene();
    car = new Car(); 	// 车，在俯视图中显示

    // 主场景
    frontScene.add(frontGroup);
    // 画虚线
    var cx = topScene.halfParkW + topScene.wayL;
    lineMaterial = dashedLineMaterial;
    frontGroup.add(hVerticalLine(cx, topScene.wayW, 0));
    frontGroup.add(hVerticalLine(-cx, topScene.wayW, 0));
    // 画道路边黄线
    lineMaterial = yellowLineMaterial;
    frontGroup.add(hHorizontalLine(-topScene.areaW, topScene.areaW, topScene.wayW));
    // 画车位白线
    lineMaterial = whiteLineMaterial;
    frontGroup.add(hHorizontalLine(-topScene.areaW, -topScene.halfParkW, 0));
    frontGroup.add(hVerticalLine(-topScene.halfParkW, 0, -topScene.parkL));
    frontGroup.add(hHorizontalLine(-topScene.halfParkW, topScene.halfParkW, -topScene.parkL));
    frontGroup.add(hVerticalLine(topScene.halfParkW, 0, -topScene.parkL));
    frontGroup.add(hHorizontalLine(topScene.halfParkW, topScene.areaW, 0));


    // test 在主场景中显示汽车后轴中心和驾驶员位置，测试全景视图时有用。
    //frontGroup.add(hHorizontalLine(-10, 10, 0)); // 场地原点
    //frontGroup.add(hHorizontalLine(car.x - 10, car.x + 10, car.y)); // 车原点
    //frontGroup.add(hHorizontalLine(car.x + car.driverX - 10, car.x + car.driverX + 10, car.y + car.driverY)); // 摄像机位置


    // 后视镜场景
    mirrorScene.add(mirrorGroup);
    // 画虚线
    var cx = topScene.halfParkW + topScene.wayL;
    lineMaterial = dashedLineMaterial;
    mirrorGroup.add(hVerticalLine(cx, topScene.wayW, 0));
    mirrorGroup.add(hVerticalLine(-cx, topScene.wayW, 0));
    // 画道边黄线
    lineMaterial = yellowLineMaterial;
    mirrorGroup.add(hHorizontalLine(-topScene.areaW, topScene.areaW, topScene.wayW));
    // 画车位白线
    lineMaterial = whiteLineMaterial;
    mirrorGroup.add(hHorizontalLine(-topScene.areaW, -topScene.halfParkW, 0));
    mirrorGroup.add(hVerticalLine(-topScene.halfParkW, 0, -topScene.parkL));
    mirrorGroup.add(hHorizontalLine(-topScene.halfParkW, topScene.halfParkW, -topScene.parkL));
    mirrorGroup.add(hVerticalLine(topScene.halfParkW, 0, -topScene.parkL));
    mirrorGroup.add(hHorizontalLine(topScene.halfParkW, topScene.areaW, 0));
    mirrorGroup.render = function () {
        mirrorGroup.rotation.z = car.anglez - car.anglez0;    //详细出处参考：http://www.jb51.net/article/32861.htm
        mirrorGroup.position.x = car.x - car.x0;              //改变了position等变量（或者直接改变position等属性）后并没有立刻更新matrix值，这时应该手动调用updateMatrix()。
        mirrorGroup.position.y = car.y - car.y0;              //改变了position等变量（或者直接改变position等属性）后并没有立刻更新matrix值，这时应该手动调用updateMatrix()。
    }
    // 建立视图，视角是视窗上下边夹角？ 参数
    var v1 = new view3d(frontScene, "leftview", 50, degree90, degree1 * 45, 0, car.driverX + 80, car.driverY, car.driverZ - 50); 	//左视图，视角50度，向下15度，向左转55度，不翻转0，基准位置x0 y0 z0
    var v2 = new view3d(frontScene, "mainview", 30, degree90, 0, 0, car.driverX, car.driverY, car.driverZ); 	//主视图，视角50度，向下12度，不转动0，不翻转0，基准位置x0 y0 z0
    //var v2 = new view3d(frontScene, "mainview", 50, 0, 0, 0, car.driverX, car.driverY, 3000); 	//主视图，视角50度，向下12度，不转动0，不翻转0，基准位置x0 y0 z0
    //var v2 = new view3d(frontScene, "mainview", 50, 90, 0, 0, x0, y0, z0); 	//主视图，视角50度，向下12度，不转动0，不翻转0，基准位置x0 y0 z0
    var v3 = new view3d(frontScene, "rightview", 50, degree90, degree1 * 300, 0, car.driverX + 90, car.driverY, car.driverZ - 50); //右视图，视角50度，向下12度，向右转110，不翻转0，基准位置x0 y0 z0
    //var v6 = new view3d(mirrorScene, "leftbackview", 50, degree90, degree1 * 170, 0, car.halfWa, car.driverY + 100, car.h1);
    //var v7 = new view3d(mirrorScene, "rightbackview", 50, degree90, degree1 * 190, 0, -car.halfWa, car.driverY + 100, car.h1);
    var v6 = new view3d(frontScene, "leftbackview", 60, degree90, degree1 * -195, 0, car.driverY - 80 * 2, -car.halfWa - 40, car.h1 - 20); //car.driverY - 80 * 2 后视镜的位置大约是从车头方向往后看
    var v7 = new view3d(frontScene, "rightbackview", 60, degree1 * 90, degree1 * -165, 0, car.driverY - 80 * 2, car.halfWa + 40, car.h1 - 20);

    //var nowtime = new Date();
    //var oldtime = nowtime;
    render = function () {
        car.move(); // 先移动车，其它场景根据车的位置渲染
        //v1.render();
        //v2.render();
        //v3.render();
        //v6.render();
        //v7.render();

        //document.getElementById('whellang').innerHTML = (car.wheelAngle / degree1).toFixed(1);
        //document.getElementById('carang').innerHTML = (car.anglez / degree1).toFixed(1);
        //document.getElementById('carx').innerHTML = car.x.toFixed(1);
        //document.getElementById('cary').innerHTML = car.y.toFixed(1);

        // 显示两帧间隔时间
        //nowtime = new Date();
        //var ts = nowtime.getTime() - oldtime.getTime();
        //document.getElementById('frames').innerHTML = ts;	// 两帧间隔时间
        //oldtime = nowtime;
    }

    render();

    var timer1 = 0;
    var pauseData;
    render.start = function () {
        if (timer1 === 0)
            timer1 = setInterval(render, period)	// 20帧
    }
    render.stop = function () {
        car.move(); // 显示车
        //if (timer1 !== 0 && car.turn === 0 && car.speed === 0) {
        if (timer1 !== 0) {
            clearInterval(timer1);
            timer1 = 0;
        }
    }

    var go = document.getElementById('go');
    go.onclick = function () {
        operation.canrun = false;	// 禁止手动操作
        render.stop();
        autopilot.start();
    }
    var previous = document.getElementById('previous');
    previous.onclick = function () {
        autopilot.previous();
    }
    var next = document.getElementById('next');
    next.onclick = function () {
        autopilot.next();
    }
    var topview = document.getElementById('hidecar');
    topview.onclick = function () {
        car.showCar = !car.showCar;
    }
}

// 二维俯视图
function TopScene() {
	lineW = 20; 	// 标识线宽度
	parkW = 240; // 车位宽
	this.parkL = 525; // 车位长
	this.wayW = 683; 	// 道路宽
	this.wayL = 683; 	// 道路长，从车位边到虚线的距离
	this.way1W = 50; 	// 路边宽度
	this.areaW = parkW + this.wayL * 2 + this.way1W * 2; // 全宽
	this.areaH = this.wayW + this.parkL + this.way1W * 2; 	// 全高

	// 画布
	var canvas = document.getElementById('topscene');
	var ww = canvas.clientWidth;
	var hh = canvas.clientHeight;
	var ctxScene = canvas.getContext('2d'); // 绘图环境

	// 根据画布比例计算比例，调整场地区域
	var scalex = ww / this.areaW;
	var scaley = hh / this.areaH;
	if (scalex > scaley) {
		scalex = scaley;
		this.areaW = ww / scalex;
	}
	else {
		scaley = scalex;
		this.areaH = hh / scaley;
	}
	this.sca = scalex;
	ctxScene.scale(scalex, scalex);

	// 以车位前边中点为原点
	this.x0 = this.areaW / 2;
	this.y0 = (this.areaH - this.parkL + this.wayW) / 2;

	this.halfParkW = parkW / 2;
	ctxScene.lineWidth = lineW;
	lineHalfWidth = lineW / 2; 	// 画3d线时用

	// 画虚线
	//var cx = this.halfParkW + this.wayL;
	//var dashArray = [50, 50];
	//ctxScene.dashedLine(this.x0 + cx, this.y0 - this.wayW, this.x0 + cx - 0.01, this.y0, dashArray); // ie10中，不加0.01不显示
	//ctxScene.dashedLine(this.x0 - cx, this.y0 - this.wayW, this.x0 - cx - 0.01, this.y0, dashArray);
	//ctxScene.stroke();
	var cx = this.halfParkW + this.wayL;
	ctxScene.beginPath();
	ctxScene.strokeStyle = dashedStyle;
	ctxScene.moveTo(this.x0 + cx, this.y0 - this.wayW);
	ctxScene.lineTo(this.x0 + cx, this.y0);
	ctxScene.moveTo(this.x0 - cx, this.y0 - this.wayW);
	ctxScene.lineTo(this.x0 - cx, this.y0);
	ctxScene.stroke();
	// 画道边黄线
	ctxScene.strokeStyle = yellowStyle;
	ctxScene.beginPath();
	ctxScene.moveTo(0, this.y0 - this.wayW);
	ctxScene.lineTo(this.areaW, this.y0 - this.wayW);
	ctxScene.stroke();
	// 画车位白线
	ctxScene.beginPath();
	ctxScene.strokeStyle = whiteStyle;
	ctxScene.moveTo(0, this.y0);
	ctxScene.lineTo(-this.halfParkW + this.x0, this.y0);
	ctxScene.lineTo(-this.halfParkW + this.x0, this.y0 + this.parkL);
	ctxScene.lineTo(this.halfParkW + this.x0, this.y0 + this.parkL);
	ctxScene.lineTo(this.halfParkW + this.x0, this.y0);
	ctxScene.lineTo(this.areaW, this.y0);
	ctxScene.stroke();
}
